home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / UTILITIE / CPU_MEMO / 3468.ZIP / POPUP.ZIP / CLINK.INC < prev    next >
Text File  |  1988-06-30  |  9KB  |  328 lines

  1. ;       CLINK.INC               C to ASM macros.
  2. ;       ---------
  3. ;       Contains several macros which are useful when writing memory-model
  4. ;       independant assembler functions to be called from 'C' functions.
  5. ;       All the macros assume the the standard sequence of:
  6. ;
  7. ;       push    bp
  8. ;       mov     bp, sp
  9. ;
  10. ;       will take place at the beginning of the assembler function. This is
  11. ;       NOT necessary if the function has no arguments.
  12. ;
  13. ;       The default memory-model is SMALL.
  14. ;       To assemble for another memory model, define the memory model on
  15. ;       the command line by MASM /D[ModelName] ...
  16. ;       Where [ModelName] is SMALL, COMPACT, MEDIUM, LARGE or HUGE.
  17. ;
  18. ;       Alternatively, you can define the memory mode within the program
  19. ;       itself by doing: [ModelName] = 1
  20. ;       This MUST be done before including CLINK.INC
  21. ;
  22. ;       FURTHER NOTE : Whenever a register or segreg is specified, you must
  23. ;       ALWAYS use lower case. (this applies to macros only!)
  24. ;
  25. ;       Finally : If you are using MASM version 4.0 or before, then you
  26. ;       will have to remove the .MODEL directive somewhere below. In that
  27. ;       case, you will also have to specify the segments that are to be used.
  28. ;       They are usually set out as follows:
  29. ;
  30. ;_TEXT  SEGMENT  BYTE PUBLIC 'CODE'
  31. ;_TEXT  ENDS
  32. ;CONST  SEGMENT  WORD PUBLIC 'CONST'
  33. ;CONST  ENDS
  34. ;_BSS   SEGMENT  WORD PUBLIC 'BSS'
  35. ;_BSS   ENDS
  36. ;_DATA  SEGMENT  WORD PUBLIC 'DATA'
  37. ;_DATA  ENDS
  38. ;DGROUP GROUP   CONST,  _BSS,   _DATA
  39. ;       ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
  40. ;
  41. ; NOTE : For LARGE CODE, then the _TEXT segment must be given a unique name.
  42. ; By convention, if the name of the module is "MOD", then the text segment
  43. ; would be declared as "MOD_TEXT". Easy really. Don't forget that the
  44. ; ASSUME reference to _TEXT would also have to be MOD_TEXT
  45. ;
  46. ; The above segments should be declared at the beginning of your assembler
  47. ; program, after including CLINK.INC, but ONLY for MASM 4.0 and earlier.
  48. ;
  49.  
  50. FALSE = 0
  51. TRUE  = 1
  52. MODEL_NAME EQU <SMALL>
  53.  
  54. ifdef COMPACT
  55. LARGE_DATA = 1
  56. MODEL_NAME EQU <COMPACT>
  57. endif
  58.  
  59. ifdef MEDIUM
  60. LARGE_CODE = 1
  61. MODEL_NAME EQU <MEDIUM>
  62. endif
  63.  
  64. ifdef LARGE
  65. LARGE_CODE = 1
  66. LARGE_DATA = 1
  67. MODEL_NAME EQU <LARGE>
  68. endif
  69.  
  70. ifdef HUGE
  71. LARGE_CODE = 1
  72. LARGE_DATA = 1
  73. MODEL_NAME EQU <HUGE>
  74. endif
  75.  
  76. .MODEL MODEL_NAME               ; Remove this line for MASM 4.0 and earlier.
  77.  
  78.  
  79. ;       Define the size of the return address stored at the top of the stack.
  80.  
  81. ifdef LARGE_CODE
  82.         CODPTRSIZ = 4
  83. else
  84.         CODPTRSIZ = 2
  85. endif
  86.  
  87. ;       Define the size of any pointer arguments.
  88.  
  89. ifdef LARGE_DATA
  90.         PTRSIZE = 4
  91. else
  92.         PTRSIZE = 2
  93. endif
  94.  
  95. ;       This next line sets up ARG1 to point at the 1st argument in the stack,
  96. ;       when it is used in conjunction with BP.
  97. ;       ( i.e. [BP+ARG1] points to the 1st argument on the stack )
  98.  
  99. ARG1 = CODPTRSIZ+2
  100.  
  101. ;       MACRO MOVARG    register, argpos
  102. ;       ------------
  103. ;       The following macro will load a word value into a specified register.
  104. ;       The word value is taken from an argument on the stack.
  105. ;       The actual argument used is arrived at by adding the specified
  106. ;       offset (arg) to BP, and using that at a pointer. The predefined value
  107. ;       ARG1 always points to the first argument on the stack. To access
  108. ;       subsequent arguments, the size of each of the preceeding arguments
  109. ;       must be computed, and added to the ARG1 offset.
  110. ;       [This macro assumes a "push bp" and "mov bp, sp" at the beginning]
  111. ;
  112. ;       Example : In 'C' :      func( int x, char *y, int z )
  113. ;
  114. ;       Load 'x' into ax    :   MOVARG  ax, ARG1
  115. ;       Load 'z' into bx    :   MOVARG  bx, ARG1+2+PTRSIZE
  116. ;       Load 'y' into es:bx :   LDPTR   es, bx, ARG1+2
  117. ;
  118. ;       The '2' refers to the size of the 'x' arg, and the PTRSIZE refers
  119. ;       to the size of the char *y [This is memory-model dependant!]
  120. ;
  121. ;       To load a pointer argument from the stack into a segreg/register pair,
  122. ;       use the LDPTR macro, described elsewhere.
  123. ;
  124. ;       NOTE: If this macro is used in conjunction with the DEFARGS macro,
  125. ;       then arguments on the stack can be referred to by name. See the
  126. ;       example under DEFARGS.
  127.  
  128. MOVARG  macro   reg, arg
  129.         mov     reg, [BP+arg]
  130. ENDM
  131.  
  132. ;       MACRO MOVLONG   reg1, reg2, arg
  133. ;       -------------
  134. ;       Moves the long referred to by "arg" into reg1 and reg2.
  135. ;       reg1 will contain the high order word, reg2 the low order word.
  136.  
  137. MOVLONG macro   reg1, reg2, arg
  138.         mov     reg1, [BP+arg+2]
  139.         mov     reg2, [BP+arg]
  140. ENDM
  141.  
  142. ;       MACRO LDPTR     segreg, offreg, argpos
  143. ;       -----------
  144. ;       This macro is used to load pointer arguments passed on the stack.
  145. ;       If LARGE_DATA is used, a 4-byte pointer will be loaded into the
  146. ;       segreg/register pair given. This is done using either the LDS or the
  147. ;       LES instruction, with the given offset register. Note that this means
  148. ;       that only the DS or ES segregs may be used.
  149. ;       If SMALL_DATA is being used, then a 2-byte pointer will be loaded
  150. ;       from the stack into the specified offset register.
  151. ;       Additionally, if the segreg is NOT ds, then the ds register will be
  152. ;       pushed and then popped into the given segreg.
  153. ;       The argpos parameter is the same as that described in the MOVARG macro.
  154.  
  155. LDPTR   macro   seg, reg, arg
  156.  
  157. ifdef   LARGE_DATA
  158.         l&seg   reg, [BP+arg]
  159. else
  160. ifdif   <ds>, <seg>
  161.         push    ds
  162.         pop     seg
  163. endif
  164.         mov     reg, [BP+arg]
  165. endif
  166.  
  167. ENDM
  168.  
  169. ;       MACRO PUSHDS
  170. ;       ------------
  171. ;       This macro simply pushes the DS register if LARGE_DATA
  172. ;
  173.  
  174. PUSHDS  macro
  175.  
  176. ifdef   LARGE_DATA
  177.         push    ds
  178. endif
  179.  
  180. ENDM
  181.  
  182. ;       MACRO POPDS
  183. ;       -----------
  184. ;       This macro simply pops the DS register if LARGE_DATA
  185.  
  186. POPDS   macro
  187.  
  188. ifdef   LARGE_DATA
  189.         pop     ds
  190. endif
  191.  
  192. ENDM
  193.  
  194. ;       MACRO STARTPROC name
  195. ;       --------------------
  196. ;       Declares the start of a procedure, declaring it as either
  197. ;       PROC NEAR or PROC FAR, depending on LARGE_CODE being defined.
  198.  
  199. STARTPROC       macro name
  200.  
  201. ifdef   LARGE_CODE
  202.  
  203. name    PROC FAR
  204.  
  205. else
  206.  
  207. name    PROC NEAR
  208.  
  209. endif
  210.  
  211.         bp_pushed = FALSE
  212.  
  213. ENDM
  214.  
  215. ;       MACRO DEFARGS name1, type1, name2, type2, ... , name5, type5
  216. ;       -------------
  217. ;       This macro should be used just after the STARTPROC macro.
  218. ;       It first pushes BP, and moves BP with SP.
  219. ;       Next it defines the names and offsets in the stack (with base BP) of
  220. ;       up to 5 arguments to be referred to by name inside the procedure.
  221. ;       Currently, the following argument types are supported :
  222. ;
  223. ;       PTR     a data pointer
  224. ;       CPTR    a code pointer
  225. ;       WORD    a word ( or int )
  226. ;       LONG    a double word (A long in 'C')
  227. ;
  228. ;       The macro defines all the names given, and assigns to them the offset
  229. ;       values to be used with BP in order to access them on the stack.
  230. ;       The names can then be used as arguments to the LDPTR and MOVARG macros.
  231. ;       To use them outside these macros, use the [BP+argname] format.
  232. ;
  233. ;       Currently not supported are BYTE and QWORD types.
  234. ;       (BYTE args are not passed, they are always converted to WORDS by 'C' )
  235. ;
  236. ;       EXAMPLE :
  237. ;       ---------
  238. ;       STARTPROC       _func                           ; Start the function
  239. ;       DEFARGS         x, WORD, y, PTR, z, LONG        ; Define args
  240. ;       MOVARG          ax, x                           ; Load AX with x
  241. ;       LDPTR           es:bx, y        ; ES:BX now contains Y
  242. ;       MOVLONG         bx, cx, z       ; bx contains HI, CX the LO word of z
  243.  
  244. DEFARGS macro nm1, tp1, nm2, tp2, nm3, tp3, nm4, tp4, nm5, tp5
  245.  
  246.         push    bp
  247.         mov     bp, sp
  248.  
  249.         bp_pushed = TRUE        ; Flag this for the RETPROC macro.
  250.  
  251. ifnb    <nm1>
  252. &nm1 = ARG1
  253. endif
  254. ifnb    <nm2>
  255. ifidn   <tp1>,<PTR>
  256. &nm2 = &nm1+PTRSIZE
  257. endif
  258. ifidn   <tp1>,<WORD>
  259. &nm2 = &nm1+2
  260. endif
  261. ifidn   <tp1>,<LONG>
  262. &nm2 = &nm1+4
  263. endif
  264. ifidn   <tp1>,<CPTR>
  265. &nm2 = &nm1+CODPTRSIZ
  266. endif
  267. endif
  268.  
  269. ifnb    <nm3>
  270. ifidn   <tp2>,<PTR>
  271. &nm3 = &nm2+PTRSIZE
  272. endif
  273. ifidn   <tp2>,<WORD>
  274. &nm3 = &nm2+2
  275. endif
  276. ifidn   <tp2>,<LONG>
  277. &nm3 = &nm2+4
  278. endif
  279. ifidn   <tp2>,<CPTR>
  280. &nm3 = &nm2+CODPTRSIZ
  281. endif
  282. endif
  283.  
  284. ifnb    <nm4>
  285. ifidn   <tp3>,<PTR>
  286. &nm4 = &nm3+PTRSIZE
  287. endif
  288. ifidn   <tp3>,<WORD>
  289. &nm4 = &nm3+2
  290. endif
  291. ifidn   <tp3>,<LONG>
  292. &nm4 = &nm3+4
  293. endif
  294. ifidn   <tp3>,<CPTR>
  295. &nm4 = &nm3+CODPTRSIZ
  296. endif
  297. endif
  298.  
  299. ifnb    <nm5>
  300. ifidn   <tp4>,<PTR>
  301. &nm5 = &nm4+PTRSIZE
  302. endif
  303. ifidn   <tp4>,<WORD>
  304. &nm5 = &nm4+2
  305. endif
  306. ifidn   <tp4>,<LONG>
  307. &nm5 = &nm4+4
  308. endif
  309. ifidn   <tp4>,<CPTR>
  310. &nm5 = &nm4+CODPTRSIZ
  311. endif
  312. endif
  313.  
  314. ENDM
  315.  
  316. ;       MACRO RETPROC
  317. ;       -------------
  318. ;       Pops BP if it was pushed (by having called DEFARGS)
  319. ;       It then returns.
  320.  
  321. RETPROC         macro
  322.  
  323. if      bp_pushed
  324.         pop     bp
  325. endif
  326.         ret
  327. ENDM
  328.